/**
 * This class represents a bit vector.
 * This class represents 32 (NEW) bits which can be manipulated 
 * through use of the methods this class provides.
 * 
 * (Note the rules are different than in the other java file)
 * The only things you are allowed to use in your code are the following
 *	    - The bitwise operators |, &, ~, ^, <<, >>
 *	    - Increment and Decrement ++, and --.  You may also use add things with 1 or subtract things with 1.
 *	    - Boolean operators ||, &&, and ! only in if statements
 *	    - Conditional statements (if, if-else, switch-case, ? :).
 *	    - Equality comparisons (==, !=, <=, >=, <, >).
 *	    - String concatenation (+) only in the toString method.
 *	    - Iteration may be used for onesCount, zerosCount, size, toString.
 *
 *	Anything not mentioned above you are not allowed to use. This includes the following but is not an exhaustive list:
 *	    - Multiplication & Division
 *	    - Addition & Subtraction with numbers other than 1.
 *      - Iteration in functions not mentioned above.
 *      - The unsigned right shift operator >>> (C does not provide this operator).
 *	    - Modulus (%)
 *	    - Any functions found in Java libraries (especially the Math library)
 *	        - Example Math.pow, Integer.bitCount, etc.
 *	    - Casting (you should not have cast anywhere!)
 *
 * @author Kyle Kelly
 *
 */
public class HW2BitVector
{
	/** 32 bit data initialized to all zeros Here is what you will be using to represent a Bit Vector */
	private int bits;
	/* You may not add any more fields to this class other than the ones given. */
	
	public static void main(String[] args)
	{
	    // Add your test cases here.
	    // Failure to add test cases will result in points taken off.
	    // You must test each function at least once.
		HW2BitVector h2 = new HW2BitVector();
		h2.set(10);
		h2.set(0);
		System.out.printf("Set 10 and 0 gives: 0x%x, expected was: 0x401 \n", h2.getBits());
		h2.clear(10);
		System.out.printf("Clearing 10 gives: 0x%x, expect was: 0x1 \n", h2.getBits());
		h2.setBitTo(1, true);
		System.out.printf("Setting 1 to true should give you 0x3, result is: 0x%x\n", h2.getBits());
		h2.clear(1);
		System.out.println("1 spot bit is false for set, isSet(1) returns: "+ h2.isSet(1));
		System.out.println("Least signifigant digit is set, so is clear should be false. isClear(0) returns: " + h2.isClear(0));
		h2.set(2);
		h2.set(4);
		System.out.printf("Expect for ones count: 0x3, result: 0x%x\n", h2.onesCount());
		System.out.printf("Expected for zeroes count: 0x1D, result: 0x%x\n", h2.zerosCount());
		System.out.printf("Expect size is 0x5, result: 0x%x\n", h2.size());
		System.out.println("toString returns: " +h2.toString()+ ", expected: 00000000000000000000000000010101");
	}
	
	public HW2BitVector()
	{
		bits = 0;
	}
	
	/**
	 * Sets the bit (to 1) pointed to by index.
	 * @param index index of which bit to set.
	 *        0 for the least significant bit (right most bit).
	 *        31 for the most significant bit.
	 */
	public void set(int index)
	{
		bits = bits | (1<<index);
	}

	/**
	 * Clears the bit (sets to 0) pointed to by index.
	 * @param index index of which bit to set.
	 * 	      0 for the least significant bit (right most bit).
	 * 	      31 for the most significant bit.
	 */
	public void clear(int index)
	{
		bits = bits & ~(1<<index);
	}

	/**
	 * Sets the bit (to the value passed in) pointed to by index.
	 * @param index index of which bit to set.
	 * 	      0 for the least significant bit (right most bit).
	 * 	      31 for the most significant bit.
	 */
	public void setBitTo(int index, boolean value)
	{
		if(value == true)
			set(index);
		else
			clear(index);
		
	}
	
	/**
	 * Returns true if the bit pointed to by index is currently set.
	 * @param index index of which bit to check.  
	 * 	      0 for the least significant bit (right most bit).
	 * 	      31 for the most significant bit.
	 * @return true if the bit is set in any other case (including index >= 32) return false.
	 */
	public boolean isSet(int index)
	{
		if (index>=32)
			return false;
		else if((bits & (1<<index)) != 0)
			return true;
		return false;
	}
	
	/**
	 * Returns false if the bit pointed to by index is currently set.
	 * @param index index of which bit to check.  
	 * 	      0 for the least significant bit (right most bit).
	 * 	      31 for the most significant bit.
	 * @return false if the bit is set in any other case (including index >= 32) return true.
	 */
	public boolean isClear(int index)
	{
		if(isSet(index) == true)
			return false;
		return true;
	}
	
	/**
	  * Returns the number of 1's current set in this bit vector.
	  * You may obviously use the ++ operator to increment your counter. 
	  */
	public int onesCount()
	{	
		int count = 0;
		for(int i = 0; i<32; i++){
			if((bits & (1<<i)) != 0)
				count++;
		}
		return count;
	}
	
	/**
	  * Returns the number of 0's currently set in this bit vector.
	  * You may obviously use the ++ operator to increment your counter. 
	  */
	public int zerosCount()
	{
		int count = 0;
		for(int i = 0; i<32; i++){
			if((bits & (1<<i)) == 0)
				count++;
		}
		return count;
	}
	
	/**
	 * Returns the "size" of this BitVector.  The size of this bit vector is defined
	 * to be the minimum number of bits that will represent all of the 1's for example
	 * the size of this bit vector 00010000 will be 5.
	 */
	public int size()
	{
		int count = 0;
		for(int i = 0; i<32; i++){
			if((bits & (1<<i)) != 0)
				count = i+1;
		}
		return count;
	}
	
	/**
	 * Returns a string representation of this object.
	 * Return a string with the binary representation of the bit vector.
	 * You may use String concatenation (+) here.
	 */
	public String toString()
	{
		String str = "";
		for(int i = 0; i<32; i++){
			if((bits & (1<<i)) !=0)
				str = "1" +str;
			else
				str ="0" + str;
		}
		return str;
	}

	public int getBits()
	{
		return bits;
	}
}
